package rulecontroller

import (
	"context"
	"encoding/json"
	"fmt"
	"vpn-management-server/logger"
	"vpn-management-server/network"
	"vpn-management-server/security/code"
	"vpn-management-server/src/dao/ruledao"
	"vpn-management-server/src/model/adminmodel"
	"vpn-management-server/src/model/rulemodel"
	"vpn-management-server/src/model/usermodel"
	"vpn-management-server/src/service/adminservice"
	"vpn-management-server/src/service/ruleservice"
)

// AddRule 添加规则
func AddRule(ctx context.Context, request *network.NetRequest, response *network.NetResponse) {
	if rule, ok := request.GetModel().(*rulemodel.Rule); ok {
		if !ruledao.HasRule(rule.Name) {
			err := ruledao.AddRule(rule)
			if err != nil {
				logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "add rule fail,err", err)
				response.Code = code.BAD_REQUEST
				response.ErrorMsg = "add rule fail"
				return
			}
			response.Code = code.SUCCESS
			logger.Logger.Infof("add rule %s success\n", rule.Name)
		} else {
			logger.Logger.ErrorfWithConn(ctx.Value("conn_id").(string), "rule %s exist\n", rule.Name)
			response.Code = code.BAD_REQUEST
			response.ErrorMsg = "rule exist"
			return
		}
	} else {
		logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "Transform interface to rule fail")
		response.Code = code.BAD_REQUEST
		response.ErrorMsg = "transform interface to rule fail"
	}
}

// GetAllRulesByPage 分页获取所有规则
func GetAllRulesByPage(ctx context.Context, request *network.NetRequest, response *network.NetResponse) {
	if ruleGet, ok := request.GetModel().(*rulemodel.GetAllRule); ok {
		var resData = struct {
			Rules []*rulemodel.Rule
			Count int
		}{}
		rules := ruledao.GetRulesByPage(ruleGet.PageSize, ruleGet.PageNo)
		count := ruledao.GetRulesCount()
		if count == -1 {
			logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "get rules by page fail")
			response.Code = code.INTERNAL_SERVER_ERROR
			response.ErrorMsg = "get rules by page fail"
			return
		}
		if count == 0 {
			logger.Logger.Warn("rule is empty")
			rules = []*rulemodel.Rule{}
		}
		resData.Rules = rules
		resData.Count = count
		data, _ := json.Marshal(resData)
		response.Data = data
		response.Code = code.SUCCESS
		logger.Logger.Info("get rules by page success\n")
	} else {
		logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "Transform interface to GetAllRule fail")
		response.Code = code.BAD_REQUEST
		response.ErrorMsg = "transform interface to GetAllRule fail"
	}
}

// DeleteRules 规则管理员/超级管理员删除规则
func DeleteRules(ctx context.Context, request *network.NetRequest, response *network.NetResponse) {
	if ruleIDList, ok := request.GetModel().(*rulemodel.RuleIDList); ok {
		err := ruleservice.DeleteRulesService(ruleIDList.IDs)
		if err != nil {
			logger.Logger.ErrorfWithConn(ctx.Value("conn_id").(string), "delete rule fail")
			response.Code = code.BAD_REQUEST
			response.ErrorMsg = "delete rules fail"
			return
		}
		// TODO 删除规则
		response.Code = code.SUCCESS
		logger.Logger.Info("delete rules success\n")
	} else {
		logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "Transform interface to rule id list fail")
		response.Code = code.BAD_REQUEST
		response.ErrorMsg = "transform interface to rule id list fail"
	}
}

// GrantRuleToUGroup 给用户组授予规则
func GrantRuleToUGroup(ctx context.Context, request *network.NetRequest, response *network.NetResponse) {
	if GrantUGroup, ok := request.GetModel().(*rulemodel.GrantUGroup); ok {
		rules := ruledao.GetUGroupRules(GrantUGroup.UGroupID)
		if IDs := ruleservice.CompareRulesListService(rules, GrantUGroup.IDs); len(IDs) > 0 {
			//ruledao.RecoverRulesFromUGroup(IDs, GrantUGroup.UGroupID)
			logger.Logger.ErrorfWithConn(ctx.Value("conn_id").(string), "rule %v exist\n", IDs)
			response.Code = code.FORBIDDEN
			response.ErrorMsg = "rule exist"
			response.Header["IDs"] = IDs
			return
		}
		err := ruledao.GrantRuleToUGroup(GrantUGroup.IDs, GrantUGroup.UGroupID, GrantUGroup.Signer)
		if err != nil {
			logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "grant rule to user group fail")
			response.Code = code.BAD_REQUEST
			response.ErrorMsg = "grant rule to user group fail"
			return
		}
		response.Code = code.SUCCESS
		logger.Logger.Info("grant rule to user group success")
	} else {
		logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "Transform interface to GrantUGroup fail")
		response.Code = code.BAD_REQUEST
		response.ErrorMsg = "transform interface to GrantUGroup fail"
	}
}

// DepriveRuleFromUGroup 取消用户组的规则 超级管理员/规则管理员可用
func DepriveRuleFromUGroup(ctx context.Context, request *network.NetRequest, response *network.NetResponse) {
	if DepriveUGroup, ok := request.GetModel().(*rulemodel.DepriveUGroup); ok {
		err := ruleservice.DepriveRulesFromUGroupService(DepriveUGroup.IDs, DepriveUGroup.UGroupID)
		if err != nil {
			logger.Logger.ErrorfWithConn(ctx.Value("conn_id").(string), "deprive user group rules fail")
			response.Code = code.BAD_REQUEST
			response.ErrorMsg = "deprive user group rules fail"
			return
		}
		response.Code = code.SUCCESS
		logger.Logger.Info("deprive user group rules success")
	} else {
		logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "Transform interface to DepriveUGroup fail")
		response.ErrorMsg = "transform interface to DepriveUGroup fail"
	}
}

// GetUGroupRulesByPage 超级管理员/规则管理员 分页获取用户组规则
// FIXME 需要进行修改 由于现在的策略是分配规则组之后 会分配规则组中的规则
// FIXME 因此超级管理员/规则管理员查看用户组规则应该 取出所有的规则之后减去规则组中的规则
func GetUGroupRulesByPage(ctx context.Context, request *network.NetRequest, response *network.NetResponse) {
	if UGroupRuleGet, ok := request.GetModel().(*rulemodel.GetUGroupRule); ok {
		var resData = struct {
			Rules          []*rulemodel.Rule
			IsDeletedArray []int
			Count          int
		}{}
		// 分页获取用户组规则
		rules, array := ruledao.GetUGroupRulesByPage(UGroupRuleGet.PageSize, UGroupRuleGet.PageNo, UGroupRuleGet.UGroupID)
		count := ruledao.GetUGroupRulesCount(UGroupRuleGet.UGroupID)
		if count == -1 {
			logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "get user group rule by page fail")
			response.Code = code.BAD_REQUEST
			response.ErrorMsg = "get user group rule by page fail"
			return
		}
		if count == 0 {
			logger.Logger.Warn("user group rule is empty")
			rules = []*rulemodel.Rule{}
		}
		resData.Rules = rules
		resData.IsDeletedArray = array
		resData.Count = count
		data, _ := json.Marshal(resData)
		response.Data = data
		response.Code = code.SUCCESS
		logger.Logger.Info("user group rule by page success\n")
	} else {
		logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "Transform interface to ruleGet fail")
		response.Code = code.BAD_REQUEST
		response.ErrorMsg = "transform interface to GetUGroupRule fail"
	}
}

// UserGroupGetRulesByPage 用户组管理员分页获取用户组规则
func UserGroupGetRulesByPage(ctx context.Context, request *network.NetRequest, response *network.NetResponse) {
	if UGroupRuleGet, ok := request.GetModel().(*rulemodel.GetUGroupRule); ok {
		var resData = struct {
			Rules []*rulemodel.Rule
			Count int
		}{}
		// 分页获取用户组规则 获取到的规则为未被删除的规则
		rules := ruledao.UGroupGetRulesByPage(UGroupRuleGet.PageSize, UGroupRuleGet.PageNo, UGroupRuleGet.UGroupID)
		count := ruledao.UGroupGetRulesCount(UGroupRuleGet.UGroupID)
		resData.Rules = rules
		resData.Count = count
		data, _ := json.Marshal(resData)
		response.Data = data
		response.Code = code.SUCCESS
		logger.Logger.Info("user group get rule by page success")
	} else {
		logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "Transform interface to ruleGet fail")
		response.Code = code.BAD_REQUEST
		response.ErrorMsg = "transform interface to GetUGroupRule fail"
	}
}

// DeleteUGroupRules 删除用户组规则
func DeleteUGroupRules(ctx context.Context, request *network.NetRequest, response *network.NetResponse) {
	if UGroupRuleIDList, ok := request.GetModel().(*rulemodel.UGroupRuleIDList); ok {
		err := ruleservice.DeleteRulesFromUGroupService(UGroupRuleIDList.IDs, UGroupRuleIDList.UGroupID)
		if err != nil {
			logger.Logger.ErrorfWithConn(ctx.Value("conn_id").(string), "delete user group rules fail")
			response.Code = code.BAD_REQUEST
			response.ErrorMsg = "delete user group rules fail"
			return
		}
		response.Code = code.SUCCESS
		logger.Logger.Info("delete user group rules success")
	} else {
		logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "Transform interface to ugroup rule id list fail")
		response.Code = code.BAD_REQUEST
		response.ErrorMsg = "transform interface to ugroup rule id list fail"
	}
}

// GrantRuleToUser 用户组管理员分配规则给用户
func GrantRuleToUser(ctx context.Context, request *network.NetRequest, response *network.NetResponse) {
	if GrantUser, ok := request.GetModel().(*rulemodel.GrantUser); ok {
		rules := ruleservice.GetUserAllRulesService(GrantUser.UserID)
		if IDs := ruleservice.CompareRulesListService(rules, GrantUser.IDs); len(IDs) > 0 {
			logger.Logger.ErrorfWithConn(ctx.Value("conn_id").(string), "rule %v exist\n", IDs)
			response.Code = code.FORBIDDEN
			response.ErrorMsg = fmt.Sprintf("rule %v exist", IDs)
			response.Header["IDs"] = IDs
			return
		}
		err := ruledao.GrantRuleToUser(GrantUser.IDs, GrantUser.UserID, GrantUser.Signer)
		if err != nil {
			logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "grant rule to user fail")
			response.Code = code.BAD_REQUEST
			response.ErrorMsg = "grant rule to user fail"
			return
		}
		response.Code = code.SUCCESS
		logger.Logger.Info("grant rule to user success")
	} else {
		logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "Transform interface to GrantUser fail")
		response.Code = code.BAD_REQUEST
		response.ErrorMsg = "transform interface to GrantUser fail"
	}
}

// DepriveRuleFromUser 用户组管理员取消分配给用户的规则
func DepriveRuleFromUser(ctx context.Context, request *network.NetRequest, response *network.NetResponse) {
	if DepriveUser, ok := request.GetModel().(*rulemodel.DepriveUser); ok {
		err := ruledao.DepriveRuleFromUser(DepriveUser.IDs, DepriveUser.UserID)
		if err != nil {
			logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "deprive rule from user fail")
			response.Code = code.BAD_REQUEST
			response.ErrorMsg = "deprive rule from user fail"
			return
		}
		response.Code = code.SUCCESS
		logger.Logger.Info("deprive rule from user success")
	} else {
		logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "Transform interface to DepriveUser fail")
		response.Code = code.BAD_REQUEST
		response.ErrorMsg = "transform interface to DepriveUser fail"
	}
}

// GetUserRuleByPage 分页得到用户的规则
func GetUserRuleByPage(ctx context.Context, request *network.NetRequest, response *network.NetResponse) {
	if UserRuleGet, ok := request.GetModel().(*rulemodel.GetUserRule); ok {
		var resData = struct {
			Rules []*rulemodel.Rule
			Count int
		}{}
		rules := ruledao.GetUserRulesByPage(UserRuleGet.PageSize, UserRuleGet.PageNo, UserRuleGet.UserID)
		count := ruledao.GetUserRulesCount(UserRuleGet.UserID)
		if count == -1 {
			logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "get rules by page fail")
			response.Code = code.INTERNAL_SERVER_ERROR
			response.ErrorMsg = "get user rules by page fail"
			return
		}
		if count == 0 {
			logger.Logger.Warn("user rule is empty")
			rules = []*rulemodel.Rule{}
		}
		resData.Rules = rules
		resData.Count = count
		data, _ := json.Marshal(resData)
		response.Data = data
		response.Code = code.SUCCESS
		logger.Logger.Info("get user rules by page success")
	} else {
		logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "Transform interface to GetUserRule fail")
		response.Code = code.BAD_REQUEST
		response.ErrorMsg = "transform interface to GetUserRule fail"
	}
}

// GetUserRule 得到用户的所有规则
func GetUserRule(ctx context.Context, request *network.NetRequest, response *network.NetResponse) {
	if userName, ok := request.GetModel().(*usermodel.UserName); ok {
		var resData = struct {
			Rules []*rulemodel.Rule
			Count int
		}{}
		rules := ruleservice.GetUserRulesByNameService(userName.Name)
		if rules == nil {
			logger.Logger.Warn("user rule is empty")
			rules = []*rulemodel.Rule{}
		}
		resData.Rules = rules
		data, _ := json.Marshal(resData)
		response.Data = data
		response.Code = code.SUCCESS
		logger.Logger.Info("get user rules by name success")
	} else {
		logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "Transform interface to UserName fail")
		response.Code = code.BAD_REQUEST
		response.ErrorMsg = "transform interface to UserName fail"
	}
}

// GetRGroupRulesByPage 分页获取某规则组中的规则
func GetRGroupRulesByPage(ctx context.Context, request *network.NetRequest, response *network.NetResponse) {
	if RGroupRuleGet, ok := request.GetModel().(*rulemodel.RGroupRuleGet); ok {
		var resData = struct {
			Rules []*rulemodel.Rule
			Count int
		}{}
		rules := ruledao.GetRGroupRuleByPage(RGroupRuleGet.PageSize, RGroupRuleGet.PageNo, RGroupRuleGet.RGroupID)
		count := ruledao.GetRGroupRuleCount(RGroupRuleGet.RGroupID)
		if count == -1 {
			logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "get rgroup rules by page fail")
			response.Code = code.INTERNAL_SERVER_ERROR
			response.ErrorMsg = "get rgroup rules by page fail"
			return
		}
		if count == 0 {
			rules = []*rulemodel.Rule{}
			logger.Logger.Warn("rgroup rule is empty")
		}
		resData.Rules = rules
		resData.Count = count
		data, _ := json.Marshal(resData)
		response.Data = data
		response.Code = code.SUCCESS
		logger.Logger.Info("get rgroup rules by page success\n")
	} else {
		logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "Transform interface to RGroupRuleGet fail")
		response.Code = code.BAD_REQUEST
		response.ErrorMsg = "transform interface to RGroupRuleGet fail"
	}
}

// GetRuleByRuleID 根据规则ID获取规则
func GetRuleByRuleID(ctx context.Context, request *network.NetRequest, response *network.NetResponse) {
	if RuleInfo, ok := request.GetModel().(*rulemodel.RuleID); ok {
		rules := ruledao.GetRuleByID(RuleInfo.ID)
		if rules == nil {
			logger.Logger.Warn("not have the rule")
			rules = &rulemodel.Rule{}
		}
		data, _ := json.Marshal(rules)
		response.Data = data
		response.Code = code.SUCCESS
		logger.Logger.Info("get rule by id success\n")
	} else {
		logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "Transform interface to RuleInfo fail")
		response.Code = code.BAD_REQUEST
		response.ErrorMsg = "transform interface to RuleInfo fail"
	}
}

// GetAllRuleInfos 获取所有的规则的ID和名字信息 目的是为了把规则分配给规则组
func GetAllRuleInfos(ctx context.Context, request *network.NetRequest, response *network.NetResponse) {
	if rank := adminservice.GetAdminRankService(ctx, request, response); rank == adminmodel.SuperAdmin || rank == adminmodel.RuleAdmin || rank == adminmodel.UserGroupAdmin {
		ruleInfos := ruledao.GetAllRuleInfos()
		if ruleInfos == nil {
			logger.Logger.Warn("rule is empty")
			ruleInfos = []*rulemodel.RuleInfo{}
		}
		data, _ := json.Marshal(ruleInfos)
		response.Data = data
		response.Code = code.SUCCESS
		logger.Logger.Info("get all rule info success")
	} else {
		logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "have no authority")
		response.Code = code.UNAUTHORIZED
		response.ErrorMsg = "have no authority"
		return
	}
}

func GetUGroupRuleInfos(ctx context.Context, request *network.NetRequest, response *network.NetResponse) {
	if UGroupID, ok := request.GetModel().(*rulemodel.UGroupID); ok {
		ruleInfos := ruledao.GetUGroupRuleInfos(UGroupID.ID)
		if ruleInfos == nil {
			logger.Logger.Warn("not have the rule")
			ruleInfos = []*rulemodel.RuleInfo{}
		}
		data, _ := json.Marshal(ruleInfos)
		response.Data = data
		response.Code = code.SUCCESS
		logger.Logger.Info("get ugroup ruleInfos success")
	} else {
		logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "Transform interface to UGroupID fail")
		response.Code = code.BAD_REQUEST
		response.ErrorMsg = "transform interface to UGroupID fail"
	}
}

func RecoverRules(ctx context.Context, request *network.NetRequest, response *network.NetResponse) {
	if UGroupRuleIDList, ok := request.GetModel().(*rulemodel.UGroupRuleIDList); ok {
		err := ruledao.RecoverRulesFromUGroup(UGroupRuleIDList.IDs, UGroupRuleIDList.UGroupID)
		if err != nil {
			logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "recover rules fail")
			response.Code = code.INTERNAL_SERVER_ERROR
			return
		}
		response.Code = code.SUCCESS
		logger.Logger.Info("recover rules success")
	} else {
		logger.Logger.ErrorWithConn(ctx.Value("conn_id").(string), "Transform interface to UGroupRuleIDList fail")
		response.Code = code.BAD_REQUEST
		response.ErrorMsg = "transform interface to UGroupRuleIDList fail"
	}
}
